# 1.mysql 文件有哪些?
- 参数文件:告诉 MvSQL 实例启动时在哪里可以找到数据库文件。并且指定某些初始化参数,这些参数定义了某种内存结构的大小等设置,还会介绍各种参数的类型。
- 日志文件:用来记录 MySQL 实例对某种条件做出响应时写入的文件,如错误日志文件、二进制日志文件、慢查询日志文件、查询日志文件等。
- 错误日志(error log)
- 二进制日志(bin log)
- 慢查询日志(slow query log)
long_query_time
默认是 10s - 查询日志(log)
- socket 文件:当用 UNIX 域套接字方式进行连接时需要的文件。
- pid 文件:MySQL 实例的进程 ID 文件。
- MySQL 表结构文件:用来存放 MySQL 表结构定义文件,文件后缀为
frm
。
索引文件:
存储引擎文件:因为 MySQL 表存储引擎的关系,每个存储引擎都会有自己的文件来保存各种数据。这些存储引擎真正存储了记录和索引等数据。
- MyISAM
- myd 文件:存放表数据文件
- myi 文件:存放表索引文件
- InnoDB
- .ibd 文件:存放表数据和表索引文件
# 2.什么是物理日志和逻辑日志?
物理日志和逻辑日志在存储内容上有很大区别,存储内容是区分它们的最重要手段。
物理日志:
存储内容:存储数据库中特定记录的变更,通常是 oriented page,即描述具体某一个 page 的修改操作;
例子:一条更新请求对应的初始值(original value)以及更新值(after value);
举例
"Page 42:image at 367,2; before:'ke';after:'ca'”
- Page 42 用于说明更新操作作用的 page;
- 367:用于说明更新操作相对于 page 的 offset;
- 2:用于说明更新操作的作用长度,即 length,2 代表仅仅修改了两个字符;
- before:‘Ke’:这里表示 undo information,也可以称为 undo log;
- after:‘ca’:这里表示 redo information,也可以称为 redo log;
逻辑日志:
- 存储内容:存储事务中的一个操作;
- 例子:事务中的 UPDATE、DELETE 以及 INSERT 操作。
# 3.mysql 的配置文件
MySQL 数据库是按如下顺序读取配置文件的。
/etc/my.cnf > /etc/mysql/my.cnf > /usr/local/mysql/etc/my.cnf > ~/my.cnf
- 系统级配置文件:MySQL 首先读取系统级配置文件,这通常是安装 MySQL 时指定的主配置文件。在 Unix/Linux 系统中,它通常是位于/etc/my.cnf 或/etc/mysql/my.cnf。
- 用户级配置文件:接下来,MySQL 会读取用户级配置文件。在 Unix/Linux 系统中,用户级配置文件通常是位于用户的主目录下的 my.cnf 文件。在 Windows 系统中,它位于用户主目录下的 my.ini 文件。
- 当前工作目录配置文件:如果在启动 MySQL 时指定了--defaults-file 选项,并且该选项指定了一个配置文件路径,则 MySQL 会读取该配置文件作为当前工作目录配置文件。
- 内置默认值:如果上述配置文件都不存在或未设置某些选项,MySQL 将使用内置的默认值来设置这些选项。
- 如果几个配置文件中都有同一个参数,MySQL 数据库会以读取到的最后一个配置文件中的参数为准。
# 4.表空间文件?
- 共享表空间:所有表的信息放在一个文件
- 独立表空间:每个表单独放在一个文件
# 5.二进制日志的作用?
二进制文件作用:
记录更改:
二进制日志(binary log)记录了对 MySQL 数据库执行更改的所有操作,但是不包括 SELECT 和 SHOW 这类操作,因为这类操作对数据本身并没有修改。然而,若操作本身并没有导致数据库发生变化,那么该操作可能也会写入二进制日志。单个二进制文件最大为 1G
.如果用户想记录 SELECT 和 SHOW 操作,那只能使用查询日志,而不是二进制日志。恢复(recovery):
某些数据的恢复需要二进制日志,例如,在一个数据库全备文件恢复后,用户可以通过二进制日志进行 point-in-time 的恢复。复制(replication):
其原理与恢复类似,通过复制和执行二进制日志使一台远程的 MySQL 数据库(一般称为 slave)与一台 MySQL 数据库(一般称为 master 或 primary)进行实时同步。审计(audit):
用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入的攻击。
# 6.binlog 的刷盘时机
mysql 通过 sync_binlog 参数控制 biglog 的刷盘时机,取值范围是 0-N:
0:不去强制要求,由系统自行判断何时写入磁盘;
1:每次 commit 的时候都要将 binlog 写入磁盘;
N:每 N 个事务,才会将 binlog 写入磁盘。
# 7.说说 binlog_format 参数?
binlog_format 参数十分重要,它影响了记录二进制日志的格式
。在 MySQL5.1 版本之前,没有这个参数。所有二进制文件的格式都是基于 SQL 语句(statement)级别的。同时,对于复制是有一定要求的。如在主服务器运行 rand、uuid 等函数
,又或者使用触发器等操作,这些都可能会导致主从服务器上表中数据的不一致(not sync)。
另一个影响是,会发现 InnoDB 存储引擎的默认事务隔离级别是 REPEATABLE READ
。这其实也是因为二进制日志文件格式的关系,如果使用 READ COMMITTED 的事务隔离级别(大多数数据库,如 Oracle, SQLServer 数据库的默认隔离级别),会出现类似丢失更新的现象,从而出现主从数据库上的数据不一致。
MySQL5.1 开始引入了 binlog_format
参数,该参数可设的值有 STATEMENT、ROW 和 MIXED。
STATEMENT、ROW 的思想类似于 redis 的 RDB 和 AOF.
- STATEMENT 格式和之前的 MySQL 版本一样,二进制日志文件记录的是日志的逻辑 SQL 语句。
在 ROW 格式下,二进制日志记录的不再是简单的 SQL 语句了,而是记录表的行更改情况
。同时,对上述提及的 Statement 格式下复制的问题予以解决。从 MySQL 5.1 版本开始,如果设置了 binlog_format 为 ROW,可以将InnoDB 的事务隔离基本设为 READ COMMITTED
,以获得更好的并发性。- 在 MIXED 格式下,MySQL 默认采用 STATEMENT 格式进行二进制日志文件的记录,但是在一些情况下会使用 ROW 格式,可能的情况有:
- 表的存储引擎为 NDB,这时对表的 DML 操作都会以 ROW 格式记录。
- 使用了 UUIDO)、USERO、CURRENT USERO)、 FOUND ROWS()、ROW COUNT()等不确定函数。
- 使用了 INSERTDELAY 语句。
- 使用了用户定义函数(UDF)。
- 使用了临时表(temporarytable)。
# 8.什么是 redo log?
MySQL 的Redo Log
(重做日志)是一种持久化日志机制,用于确保即使在数据库崩溃或突然重启等异常情况下,事务的持久性(Durability,ACID 属性的一个组成部分)仍然能得到保证。
具体来说,当一个事务进行更改(例如,INSERT、UPDATE、DELETE 等操作)时,这些更改首先会被写入到 Redo Log 中。这个过程通常是非常快的,因为只需要写入到磁盘的顺序部分,而不需要直接更新磁盘上的数据文件。一旦 Redo Log 被安全地写入,事务就可以被认为是“提交”的,从而满足持久性的要求。
Redo Log 通常分为两部分:
In-memory Redo Log Buffer:这是内存中的一个缓冲区,用于暂存即将写入磁盘的 Redo Log 记录。
On-disk Redo Log Files:这些是磁盘上的物理文件,用于持久化存储 Redo Log 数据。这些文件通常是循环使用的(也就是说,当达到一定大小后,旧的日志记录会被覆盖)。
在数据库恢复(Recovery)过程中,Redo Log 用于“重做”事务,以确保所有提交的事务都得到应用,而所有未提交的事务都被回滚,从而达到一致性的状态。
使用 Redo Log 有多个好处:
- 提高性能:由于 Redo Log 是顺序写入的,因此具有更高的 I/O 性能。
- 数据安全性:即使在系统崩溃的情况下,也能通过 Redo Log 恢复数据,保证数据的持久性。
- 简化恢复过程:由于 Redo Log 包含了如何从一个一致状态转变到另一个一致状态的所有信息,因此数据库恢复变得相对简单和快速。
MySQL 的 Redo Log 是一种关键的持久化机制,用于保证事务的持久性并提高系统的整体性能和可靠性。
# 9.重做日志块?
在 InnoDB 存储引擎中,重做日志都是以 512 字节进行存储的
。这意味着重做日志缓存、重做日志文件都是以块(block)
的方式进行保存的,称之为重做日志块(redo log block)
,每块的大小为 512 字节。若一个页中产生的重做日志数量大于 512 字节,那么需要分割为多个重做日志块进行存储。此外,由于重做日志块的大小和磁盘扇区大小一样,都是 512 字节,因此重做日志的写入可以保证原子性,不需要 double write 技术
。
重做日志块除了日志本身之外,还由日志块头(log block header)及日志块尾(log block tailer)两部分组成。重做日志头一共占用 12 字节,重做日志尾占用 8 字节。故每个重做日志块实际可以存储的大小为 492 字节
(512-12-8)。
日志块头(log block header)由四部分组成.
log buffer 是由 log block 组成,在内部 log buffer 就好似一个数组,因此 LOG_BLOCK_HDR_NO 用来标记这个数组中的位置。其是递增并且循环使用的,占用 4 个字节,但是由于第一位用来判断是否是 flush bit,所以最大的值为 2G。
LOG_BLOCK_HDR_DATA_LEN 占用 2 字节,表示 log block 所占用的大小。当 log block 被写满时,该值为 0x200,表示使用全部 log block 空间,即占用 512 字节。
LOG_BLOCK_FIRST_REC_GROUP 占用 2 个字节,表示 log block 中第一个日志所在的偏移量。如果该值的大小和 LOG_BLOCK_HDR_DATA_LEN 相同,则表示当前 log block 不包含新的日志。
LOG_BLOCK_CHECKPOINT_NO 最后被写入的检查点的位置.占用 4 个字节.
# 10.重做日志缓冲?
InnoDB 存储引擎的内存区域除了有缓冲池外,还有重做日志缓冲(redo log buffer)
。InnoDB 存储引擎首先将重做日志信息先放入到这个缓冲区,然后按一定频率将其刷新到重做日志文件。重做日志缓冲一般不需要设置得很大,因为一般情况下每一秒钟会将重做日志缓冲刷新到日志文件,因此用户只需要保证每秒产生的事务量在这个缓冲大小之内即可。该值可由配置参数 innodb_log_buffer_size
进行设置,8.0 版本默认是 16M
.
重做日志缓冲刷新到磁盘的情况
- Master Thread 每一秒将重做日志缓冲刷新到重做日志文件;
- 每个事务提交时会将重做日志缓冲刷新到重做日志文件;
- 当重做日志缓冲池剩余空间小于 1/2 时,重做日志缓冲刷新到重做日志文件。
# 11.重做日志文件?
在默认情况下,在 InnoDB 存储引擎的数据目录下会有两个名为ib_logfile0 和 ib_logfile1
的文件。是重做日志文件(redo log file)
。它们记录了对于 InnoDB 存储引擎的事务日志。当实例或介质失败(media failure)时,重做日志文件就能派上用场。例如,数据库由于所在主机掉电导致实例失败,InnoDB 存储引擎会使用重做日志恢复到掉电前的时刻,以此来保证数据的完整性。
每个 InnoDB 存储引擎至少有 1 个重做日志文件组(group)
,每个文件组下至少有 2 个重做日志文件
,如默认的 ib_logfile0 和 ib_logfile1。为了得到更高的可靠性,用户可以设置多个的镜像日志组(mirrored log groups),将不同的文件组放在不同的磁盘上,以此提高重做日志的高可用性。在日志组中每个重做日志文件的大小一致,并以循环写入的方式运行。InnoDB 存储引擎先写重做日志文件 1,当达到文件的最后时,会切换至重做日志文件 2
- innodb_log_fle_size:每个重做日志文件的大小 最大 512G
- innodb_log_flesin_group:组中重做日志文件的数量 默认为 2
- innodb_mirrored_log_groups:日志镜像文件组的数量,默认为 1
- innodb_log_group_home_dir:日志文件组所在路径
- 一组两个重做日志文件的默认大小通常是 48MB,即每个文件大小为 48MB。
# 12.重做日志块与重做日志文件
重做日志(Redo Log)是数据库管理系统中的一种重要机制,用于保证事务的持久性和数据恢复。在 MySQL 等数据库管理系统中,重做日志通常由多个重做日志文件组成,每个文件由多个重做日志块组成。
重做日志块(Redo Log Block):
- 重做日志块是重做日志的最小单位,通常是一个固定大小的数据块。
- 它记录了数据库中发生的每个事务所进行的修改操作,如更新、插入和删除等。
- 当事务执行修改操作时,先将修改记录到重做日志块,然后再将修改应用到内存中的数据页上。
- 重做日志块是顺序写入的,因为它需要保证记录的顺序与事务的执行顺序一致。
- 一旦事务将修改记录到重做日志块并提交,数据库就可以认为该事务的修改已经持久化,并可以在必要时进行恢复。
重做日志文件(Redo Log File):
- 重做日志文件是由多个重做日志块组成的逻辑文件,用于存储重做日志的内容。
- 重做日志文件是一个循环的文件组,当写满一个重做日志文件后,数据库会切换到下一个重做日志文件,以保证循环使用。
- 在数据库运行期间,重做日志文件会不断地写入新的重做日志块,并且不会删除已经写入的内容,这是为了确保发生故障时可以进行数据恢复。
- 当数据库发生崩溃或意外停机时,重做日志文件中的内容将被用于恢复未提交的事务和未写入磁盘的数据页,以保证数据的一致性。
总结:
- 重做日志块是重做日志的最小记录单位,记录每个事务的修改操作。
- 重做日志文件是由多个重做日志块组成的逻辑文件,用于存储重做日志的内容,确保数据的持久性和一致性,以及在数据库崩溃时进行恢复。
# 13.重做日志的格式?
在 InnoDB 存储引擎中,对干各种不同的操作有着不同的重做日志格式。到 InnoDB1.2.x 版本为止,总共定义了 51 种重做日志类型。虽然各种重做日志的类型不同,但是它们有着基本的格式,表 3-2 显示了重做日志条目的结构:
- redo_log_type 占用 1 字节,表示重做日志的的类型
- space 表示表空间的 ID,但采用压缩的方式,因此占用的空间可能小于 4 字节
- page_no 表示页的偏移量,同样采用压缩的方式
- redo_log_body 表示每个重做日志的数据部分,恢复时需要调用相应的函数进行解析
# 14.重做日志刷盘机制
从重做日志缓冲往磁盘写入时,是按 512 个字节,也就是一个扇区的大小进行写入。因为扇区是写入的最小单位,因此可以保证写入必定是成功的。因此在重做日志的写入过程中不需要有 double write.
从重做日志缓冲写入磁盘上的重做日志文件是按一定条件进行的,
- 在主线程中每秒会将重做日志缓冲写入磁盘的重做日志文件中,不论事务是否已经提交。
- 另一个触发写磁盘的过程是由参数
innodb_flush_log_at_trx_commit
控制,表示在提交(commit)操作时,处理重做日志的方式。参数 innodb_flush_log_at_trx_commit 的有效值有 0 1 2。- 0 代表当提交事务时,并不将事务的重做日志写入磁盘上的日志文件,而是等待主线程每秒的刷新。
- 1 表示在执行 commit 时将重做日志缓冲同步写到磁盘,即伴有 fsync 的调用。
- 2 表示将重做日志异步写到磁盘,即写到文件系统的缓存中。因此不能完全保证在执行 commit 时肯定会写入重做日志文件,只是有这个动作发生。
因此为了保证事务的 ACID 中的持久性,必须将 innodb_flush_log_at_trx_commit
设置为 1,也就是每当有事务提交时,就必须确保事务都已经写入重做日志文件。那么当数据库因为意外发生宕机时,可以通过重做日志文件恢复,并保证可以恢复已经提交的事务。而将重做日志文件设置为 0 或 2,都有可能发生恢复时部分事务的丢失。不同之处在于,设置为 2 时,当 MySQL 数据库发生宕机而操作系统及服务器并没有发生宕机时,由于此时未写入磁盘的事务日志保存在文件系统缓存中,当恢复时同样能保证数据不丢失。
# 15.什么是 LSN?
LSN(Log Sequence Number)是数据库中用于标识事务日志(重做日志)顺序的一种递增的序列号。LSN 在数据库中扮演着非常重要的角色,用于管理事务的提交和回滚、故障恢复以及数据一致性等方面。
LSN 的作用:
- 标识事务日志的顺序:每当一个事务进行数据修改时,相关的重做日志(Redo Log)记录会被生成,并分配一个唯一的 LSN 号。这样,数据库系统就可以通过 LSN 来确定事务日志的顺序,从而保证修改的顺序与事务的执行顺序一致。
- 事务的提交和回滚:数据库系统使用 LSN 来跟踪和管理事务的提交和回滚。当一个事务提交时,其对应的 LSN 会被记录在持久化存储中,以确保在故障恢复时,可以正确地重新执行已提交的事务。而在事务回滚时,数据库可以利用 LSN 来撤销事务所做的修改。
- 故障恢复:在数据库系统发生崩溃或异常停机时,通过 LSN 可以确定在故障发生前已经提交的事务,以及还未提交的事务。通过重做日志和 LSN,数据库可以重新执行已提交的事务,确保数据的持久性和一致性。
- 数据一致性:在数据库的恢复过程中,LSN 可以确保已提交事务的修改在崩溃后重新执行,从而维护数据的一致性。
总结: LSN(Log Sequence Number)是数据库中用于标识事务日志顺序的递增序列号。通过 LSN,数据库系统可以管理事务的提交和回滚,实现故障恢复,并保证数据的一致性。LSN 在数据库的可靠性和恢复方面起着重要的作用。
# 16.binlog 和重做日志区别?
在 MySQL 数据库中还有一种二进制日志(binlog),其用来进行 POINT-IN-TIME(PIT)的恢复及主从复制(Replication)环境的建立。从表面上看其和重做日志非常相似,都是记录了对于数据库操作的日志。然而,从本质上来看,两者有着非常大的不同。
首先,重做日志是在 InnoDB 存储引擎层产生
,而二进制日志是在 MySQL 数据库的上层产生的
,并且二进制日志不仅仅针对于 InnoDB 存储引擎,MySQL 数据库中的任何存储引擎对于数据库的更改都会产生二进制日志。
其次,两种日志记录的内容形式不同。MySQL 数据库上层的二进制日志是一种逻辑日志
,其记录的是对应的 SQL 语句。而 InnoDB 存储引擎层面的重做日志是物理格式日志
,其记录的是对于每个页的修改。
此外,两种日志记录写入磁盘的时间点不同,二进制日志只在事务提交完成后进行一次写入
。 而 InnoDB 存储引擎的重做日志在事务进行中不断地被写入
,这表现为日志并不是随事务提交的顺序进行写入的。
二进制日志仅在事务提交时记录,并且对于每一个事务,仅包含对应事务的一个日志。而对于 InnoDB 存储引擎的重做日志,由于其记录的是物理操作日志,因此每个事务对应多个日志条目,并且事务的重做日志写入是并发的,并非在事务提交时写入,故其在文件中记录的顺序并非是事务开始的顺序。
# 17.什么是 undo log?
Undo Log(撤销日志)是数据库管理系统中的另一个关键机制,用于支持事务的回滚和并发控制。在 MySQL 等数据库中,每个事务执行期间所做的修改操作除了被记录到重做日志(Redo Log)中,还会被记录到 Undo Log 中。
undo log 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,重做日志记录数据被修改后的信息。undo log 主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。
Undo Log 的作用:
- 支持事务的回滚:当一个事务需要回滚(撤销)时,数据库可以利用 Undo Log 中的信息将事务所做的修改操作逆向执行,从而撤销该事务对数据所做的改变。
- 实现并发控制:当一个事务在执行期间,可能会读取其他事务正在修改的数据。为了确保事务的读取操作能够得到一致性的数据,数据库会将其他事务正在修改的数据版本记录到 Undo Log,这样在读取时,可以根据 Undo Log 中的数据版本来获取一个一致性的数据视图。
Undo Log 的工作原理:
- 在事务执行期间,如果进行了数据的修改(例如插入、更新、删除等),数据库会先将修改前的数据记录到 Undo Log 中,保留原始数据的一个副本。
- 当事务提交时,Undo Log 中的记录被保留,用于可能的回滚操作,以确保事务的原子性和一致性。
- 如果事务执行过程中发生错误,或者事务被回滚,数据库可以利用 Undo Log 中的信息将事务的修改操作逆向执行,从而回滚事务。
- 并发控制方面,当一个事务需要读取数据时,数据库会检查其他正在执行的事务是否已经修改过该数据。如果是,数据库可以通过 Undo Log 中的数据版本来提供给读取操作一个一致性的数据视图。
总结:
Undo Log 是数据库中用于支持事务回滚和实现并发控制的机制。它记录了事务执行过程中所做的数据修改操作的原始值,以便在事务回滚或提供一致性读取时使用。通过 Undo Log,数据库可以保证事务的原子性、一致性和隔离性。
除了回滚操作,undo log 的另一个作用是 MVCC,即在 InnoDB 存储引擎中 MVCC 的实现是通过 undo log 来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过 undo log 读取之前的行版本信息,以此实现非锁定读取。
# 18.举例说明重做日志的作用
- DB_TRX_ID:记录创建这条记录/最后一次修改该记录的事务 ID
- DB_ROW_ID: 隐含的自增 ID
- DB_ROLL_PTR: 指向这条记录的上一个版本
# 19.undo log 和 redo log?
事务隔离性由锁来实现。原子性、一致性、持久性由数据库的 redo log 和 undo log 来完成。
redo log 称为重做日志来保证事务的原子性和持久性。
undo log 用来保证事务的一致性。
undo 不是 redo 的逆过程。redo log 和 undo log 的作用都可以视为是一种恢复操作,redo 恢复提交事务修改页操作,而 undo 回滚行记录到某个特定版本
。因此两者记录的不同,redo 通常是物理日志,记录的是页的物理修改操作。undo 逻辑日志,根据每行记录进行记录
。
在 MySQL 中,重做日志(Redo Log)是用于保证事务的持久性(Durability)的一种机制。它由两部分组成:重做日志缓冲(Redo Log Buffer)和重做日志文件(Redo Log File)。
重做日志缓冲是一个内存区域,用于暂存事务执行过程中对数据的修改操作。当事务提交时,重做日志缓冲中的内容会被刷写到重做日志文件中。
重做日志文件是一个磁盘文件,用于记录所有的事务修改操作。当数据库发生宕机等异常情况时,重做日志文件可以用来恢复数据。重做日志文件的大小是固定的。重做日志的作用是保证事务的持久性和可恢复性。
redo log 存放在重做日志文件中,与 redo log 不同,undo 存放在数据库内部的一个特殊段(segment)中,这个段称为 undo 段(undo segment)。undo 段位于共享表空间内。可以通过 py_innodb_page_info.py 工具来查看当前共享表空间中 undo 的数量。
最后也是最为重要的一点是,undo log 会产生 redo log,也就是 undo log 的产生会伴随着 redo log 的产生,这是因为 undo log 也需要持久性的保护。
# 20.慢查询日志
程序中定位一个执行慢的 SQL 可以根据慢查询日志,默认情况下,慢查询日志禁用,因为开启慢查询日志或多或少的会对 mysql 的性能产生一些影响。在慢查询日志功能开启时,只有 SQL 执行时间超过 long_query_time
参数值的的语句才会在慢查询日志中记录。long_query_time
参数,最小值和默认值分别为 0 10,单位为秒。
slow_query_log:是否开启慢查询日志
long_query_time:查询阈值,超过了该阈值则记录到慢查询日志中
log_output:如何存储慢查询日志,可选项:FILE 或者 TABLE
slow_query_log_file:以 FILE 类型存储慢查询日志时的存储位置
set global slow_query_log=on;
mysql> select sleep(11);
2